// #include "http_server.h"

// #include "esp_rom_md5.h"
// #include "esp_spi_flash.h"
// #include "esp_partition.h"
// #include "esp_flash_partitions.h"
// #include "http_tools.h"
// #include "esp_log.h"

// #define TAG "httpd.FileManager"
// #define log_e(...) ESP_LOGE(TAG, __VA_ARGS__)
// #define log_i(...) ESP_LOGI(TAG, __VA_ARGS__)
// #define log_w(...) ESP_LOGW(TAG, __VA_ARGS__)

// uint32_t files_to_web_cb(uint8_t *buff, uint32_t len, void *user_data)
// {
//     return httpd_resp_send_chunk(user_data, (char *)buff, len) == ESP_OK ? len : 0;
// }

// /* GET html Page */
// esp_err_t file_manager_handle(httpd_req_t *req)
// {
//     printf("[/file manager/*] file name : %s\n", req->uri);
//     http_server_t server = httpd_get_global_user_ctx(req->handle);
// #if HTTPD_SERVER_ENABLE_AUTH
//     if (!http_server_check_ip_auth(req))
// #endif
//     {
//         get_path_from_uri(server->path, (char *)req->user_ctx, "/file_manager.html", sizeof(server->path));
//         return httpd_send_file(req, server->path);
//     }
// #if HTTPD_SERVER_ENABLE_AUTH
//     else
//     {
//         get_path_from_uri(server->path, (char *)req->user_ctx, "/login.html", sizeof(server->path));
//         return httpd_send_file(req, server->path);
//     }
//     httpd_resp_sendstr_chunk(req, NULL);
//     return ESP_OK;
// #endif
// }
// /**
//  *      Get File list(POST)
//  *      {
//  *          "path": path
//  *      }
//  */
// static esp_err_t file_manager_get_list_handle(httpd_req_t *req)
// {
//     if (!http_server_auth_check(req))
//     {
// #ifdef CONFIG_LIBS_USE_CJSON
//         http_server_t server = httpd_get_global_user_ctx(req->handle);
//         cJSON *json = http_server_data_parse_to_json(req, 1);
//         if (json)
//         {
//             if (json_object_has_item(req, json, "path")) /* 并且存在 path 字段 */
//             {
//                 struct stat infos;
//                 char *path = json_get_string(req, json, "path");
//                 char path_buff[256];
//                 strcpy(path_buff, path);
//                 if (json_object_has_item(NULL, json, "name")) /* 查找文件 */
//                 {
//                     printf("[web.file.get] find %s form %s\n", json_get_string(req, json, "name"), path_buff);
//                     server->data[0] = '[';
//                     httpd_resp_send_chunk(req, (char *)server->data, 1);
//                     find_name_to_cb(path_buff, json_get_string(req, json, "name"), server->data, 0, files_to_web_cb, req);
//                     server->data[0] = ']';
//                     httpd_resp_send_chunk(req, (char *)server->data, 1);
//                 }
//                 else if (!strcmp(path, "/")) /* 遍历根目录 */
//                 {
//                     list_files_to(path_buff, (char *)server->data, 4096);
//                     httpd_resp_sendstr_chunk(req, (char *)server->data);
//                 }
//                 else if (stat(path, &infos) != -1)
//                 {
//                     if (infos.st_mode & S_IFDIR) /* 遍历目录 */
//                         list_files_to_cb(path_buff, files_to_web_cb, req);
//                     else if (infos.st_mode & S_IFREG) /* 获取文件 */
//                     {
//                         FILE *fd = fopen(path, "r");
//                         fseek(fd, 0, SEEK_END);
//                         char file_size_str[15] = {0};
//                         sprintf(file_size_str, "%ld", ftell(fd));
//                         httpd_resp_set_hdr(req, "Content-Length", file_size_str);
//                         fseek(fd, 0, SEEK_SET);
//                         uint32_t read_size;
//                         if (fd)
//                         {
//                             do
//                             {
//                                 read_size = fread(server->data, 1, sizeof(server->data), fd);
//                                 if (read_size)
//                                 {
//                                     httpd_resp_send_chunk(req, (const char *)server->data, read_size);
//                                     if (read_size != sizeof(server->data))
//                                         break;
//                                 }
//                             } while (read_size);
//                             fclose(fd);
//                         }
//                     }
//                 }
//             }
//             cJSON_Delete(json);
//         }
// #endif
//     }
//     httpd_resp_sendstr_chunk(req, NULL);
//     return ESP_OK;
// }
// /**
//  *      Change File(POST)
//  *      1. new file
//  *      2. change file content
//  *      3. deleta file
//  *      {
//  *          "path"  : path,
//  *          "type"  : 0(update) 1(delete) 2(create folder),
//  *          "count" : pack_number,
//  *          "content": content
//  *      }
//  */
// static esp_err_t file_manager_change_handle(httpd_req_t *req)
// {
//     if (!http_server_auth_check(req))
//     {
// #ifdef CONFIG_LIBS_USE_CJSON
//         cJSON *json = http_server_data_parse_to_json(req, 1);
//         if (json)
//         {
//             if (json_object_has_item(req, json, "path") && json_object_has_item(req, json, "type")) /* 并且存在 path & type 字段 */
//             {
//                 int type = cJSON_GetInt(json, "type");
//                 if (-1 < type && type < 4)
//                 {
//                     char *path = json_get_string(req, json, "path");
//                     if (path)
//                     {
//                         if (type == 3)
//                         {
//                             char *re_name = json_get_string(req, json, "name");
//                             if (re_name)
//                             {
//                                 struct stat file_stat;
//                                 if (stat(path, &file_stat) != -1)
//                                 {
//                                     if (rename(path, re_name))
//                                         req_send_err("The directory is not empty");
//                                     else
//                                         req_send_ok();
//                                 }
//                                 else
//                                     req_send_err("File does not exist");
//                             }
//                             else
//                                 req_send_err("The name must exist");
//                         }
//                         else if (type == 1)
//                         {
//                             struct stat file_stat;
//                             if (stat(path, &file_stat) != -1)
//                             {
//                                 if (remove(path))
//                                     req_send_err("The directory is not empty");
//                                 else
//                                     req_send_ok();
//                             }
//                             else
//                                 req_send_err("File does not exist");
//                         }
//                         else if (type == 2)
//                         {
//                             char *p = strrchr(path, '/');
//                             if (p && p != path)
//                                 mkdirs(path);
//                             if (dir_exist(path))
//                                 req_send_ok();
//                             else
//                                 req_send_err("Failed to create Folder.");
//                         }
//                         else if (type == 0)
//                         {
//                             /* 创建目录 */
//                             char *p = strrchr(path, '/');
//                             if (p && p != path)
//                             {
//                                 p[0] = '\0';
//                                 mkdirs(path);
//                                 p[0] = '/';
//                             }
//                             FILE *fd = fopen(path, "w");
//                             if (fd)
//                             {
//                                 if (cJSON_HasObjectItem(json, "content"))
//                                 {
//                                     char *content = json_get_string(req, json, "content");
//                                     if (cJSON_HasObjectItem(json, "count"))
//                                         fseek(fd, cJSON_GetInt(json, "count") * 3072, SEEK_CUR);
//                                     fwrite(content, 1, strlen(content), fd);
//                                     req_send_ok();
//                                 }
//                                 else
//                                     req_send_ok();
//                                 fclose(fd);
//                             }
//                             else
//                                 req_send_err("Failed to open file");
//                         }
//                     }
//                     else
//                         req_send_err("The path must exist");
//                 }
//                 else
//                     req_send_err("Type value error");
//             }
//             cJSON_Delete(json);
//         }
// #endif
//     }
//     httpd_resp_sendstr_chunk(req, NULL);
//     return ESP_OK;
// }

// #define MAX_FILE_SIZE (5 * 1024 * 1024) // 5MB
// #define MAX_FILE_SIZE_STR "5MB"
// /* Scratch buffer size */
// #define SCRATCH_BUFSIZE 4096

// /* 函数：将ASCII码表示形式的字符转换为对应的字符 */
// uint8_t convertASCIIToChar(const char *input)
// {
//     uint8_t result;
//     char tmp[3] = {0};
//     snprintf(tmp, 3, "%s", input);
//     sscanf(tmp, "%hhX", &result);
//     return result;
// }

// /* 函数：将ASCII码表示形式的URL转换为uint8_t类型 */
// void url2ascii(const char *input, char *output, size_t outputSize)
// {
//     size_t inputLen = strlen(input);
//     size_t outputLen = 0;
//     for (size_t i = 0; i < inputLen; i++)
//     {
//         // 判断是否为ASCII码形式的字符
//         if (input[i] == '%' && i + 2 < inputLen) /* 转换为对应的字符 */
//         {
//             if (outputLen + 1 > outputSize) /* 输出缓冲区不足 */
//                 break;
//             output[outputLen++] = convertASCIIToChar(&input[i + 1]);
//             i += 2;
//         }
//         else /* 非ASCII码形式的字符直接复制到输出 */
//         {
//             if (outputLen + 1 > outputSize)
//                 break; /* 输出缓冲区不足 */
//             output[outputLen++] = input[i];
//         }
//     }
//     output[outputLen] = '\0';
// }

// /* Handler to upload a file onto the server */
// static esp_err_t file_manager_binary_update_handle(httpd_req_t *req)
// {
//     if (http_server_auth_check(req))
//     {
//         httpd_resp_sendstr_chunk(req, NULL);
//         return ESP_OK;
//     }

//     http_server_t server = httpd_get_global_user_ctx(req->handle);
//     char *filepath = (char *)server->data;
//     FILE *fd = NULL;
//     // if (req->user_ctx)
//     //     snprintf(filepath, 512, "%s%s", (const char *)req->user_ctx, req->uri + sizeof("/file_stream") - 1);
//     // else
//     url2ascii(req->uri + sizeof("/file_stream") - 1, filepath, 512); /* URL 转码 */

//     const char *filename = filepath;
//     if (!filename || strlen(&strrchr(filename, '/')[1]) > 255)
//     {
//         /* Respond with 500 Internal Server Error */
//         httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Filename too long");
//         return ESP_FAIL;
//     }

//     /* Filename cannot have a trailing '/' */
//     if (filename[strlen(filename) - 1] == '/')
//     {
//         log_e("Invalid filename : %s", filename);
//         httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Invalid filename");
//         return ESP_FAIL;
//     }

//     /* File cannot be larger than a limit */
//     // if (req->content_len > MAX_FILE_SIZE)
//     // {
//     //     log_e("File too large : %d bytes", req->content_len);
//     //     /* Respond with 400 Bad Request */
//     //     httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST,
//     //                         "File size must be less than " MAX_FILE_SIZE_STR "!");
//     //     /* Return failure to close underlying connection else the
//     //      * incoming file content will keep the socket busy */
//     //     return ESP_FAIL;
//     // }

//     if (!strcmp("/update.bin", filename) && req->content_len <= sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t) + sizeof(esp_app_desc_t))
//     {
//         log_e("This is file is not upgrade image desc.");
//         /* Respond with 400 Bad Request */
//         httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "This is file is not upgrade image desc");
//         return ESP_FAIL;
//     }

//     /* 创建目录 */
//     char *p = strrchr(filepath, '/');
//     if (p && p != filepath)
//     {
//         p[0] = '\0';
//         mkdirs(filepath);
//         p[0] = '/';
//     }
//     fd = fopen(filepath, "w");
//     if (!fd)
//     {
//         log_e("Failed to create file : %s", filepath);
//         /* Respond with 500 Internal Server Error */
//         httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to create file");
//         return ESP_FAIL;
//     }

//     log_i("Receiving file : %s...", filename);

//     /* Retrieve the pointer to scratch buffer for temporary storage */
//     char *buf = (char *)server->data;
//     int received;
//     uint8_t check = 0, is_update_bin = 0;
//     md5_context_t context;

//     if (strstr(filename, "app") && strstr(filename, ".bin"))
//         is_update_bin = 1;

//     /* Content length of the request gives
//      * the size of the file being uploaded */
//     int remaining = req->content_len;

//     while (remaining > 0)
//     {
//         // log_i("Remaining size : %d", remaining);
//         /* Receive the file part by part into a buffer */
//         if ((received = httpd_req_recv(req, buf, MIN(remaining, SCRATCH_BUFSIZE))) <= 0)
//         {
//             if (received == HTTPD_SOCK_ERR_TIMEOUT)
//             {
//                 /* Retry if timeout occurred */
//                 continue;
//             }

//             /* In case of unrecoverable error,
//              * close and delete the unfinished file*/
//             fclose(fd);
//             unlink(filepath);

//             log_e("File reception failed!");
//             /* Respond with 500 Internal Server Error */
//             httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to receive file");
//             return ESP_FAIL;
//         }

//         if (is_update_bin)
//         {
//             if (!check)
//             {
//                 check = 1;
//                 is_update_bin = 1;
//                 int app_desc_offset = sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t);
//                 esp_app_desc_t *app_info = (esp_app_desc_t *)&buf[app_desc_offset];
//                 esp_app_desc_t run_app_info = {0};
//                 esp_ota_get_partition_description(esp_ota_get_running_partition(), &run_app_info);
//                 if (app_info->magic_word != ESP_APP_DESC_MAGIC_WORD)
//                 {
//                     log_e("The updated image is not an ESP-IDF image.");
//                     httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "The updated image is not an ESP-IDF image.");
//                     fclose(fd);
//                     unlink(filepath);
//                     return ESP_FAIL;
//                 }
//                 if (memcmp(app_info->version, run_app_info.version, sizeof(app_info->version)) == 0)
//                 {
//                     log_e("The version is consistent and no update is required. restart device.");
//                     httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "The version is consistent and no update is required. restart device.");
//                     fclose(fd);
//                     unlink(filepath);
//                     return ESP_FAIL;
//                 }
//                 esp_rom_md5_init(&context);
//             }
//             else
//                 esp_rom_md5_update(&context, (unsigned char *)buf, received);
//         }

//         // mbedtls_md5_update(&md5_ctx, (uint8_t *)buf, received);
//         if (received && (received != fwrite(buf, 1, received, fd)))
//         {
//             /* Couldn't write everything to file!
//              * Storage may be full? */
//             fclose(fd);
//             unlink(filepath);

//             log_e("File write failed!");
//             /* Respond with 500 Internal Server Error */
//             httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to write file to storage");
//             return ESP_FAIL;
//         }

//         /* Keep track of remaining size of
//          * the file left to be uploaded */
//         remaining -= received;
//     }

//     /* Close file upon upload completion */
//     fclose(fd);
//     log_i("File reception complete");

//     if (is_update_bin)
//     {
//         uint8_t md5[16] = {0};
//         esp_rom_md5_final(md5, &context);
//         // mbedtls_md5_finish(&md5_ctx, md5);
//         char *md5_str = get_hex_str(md5, 16);
//         if (md5_str)
//         {
//             uint16_t len = strlen(filepath);
//             filepath[len - 3] = 'm';
//             filepath[len - 2] = 'd';
//             filepath[len - 1] = '5';
//             printf("[file_upload] mk md5 file : %s\n", filepath);
//             FILE *md5_fd = fopen(filepath, "w+");
//             if (md5_fd)
//             {
//                 fprintf(md5_fd, "%s", md5_str);
//                 fclose(md5_fd);
//             }
//         }
//     }

//     /* Redirect onto root to see the updated file list */
//     httpd_resp_sendstr(req, "File uploaded successfully");
//     httpd_resp_sendstr_chunk(req, NULL);
//     return ESP_OK;
// }

// void file_manager_server_init(httpd_handle_t server, char *base_path)
// {
//     if (!server)
//         return;
//     httpd_uri_t file_manager_get = {
//         .uri = "/file_manager/get", // Match all URIs of type /upload/path/to/file
//         .method = HTTP_POST,
//         .user_ctx = base_path,
//         .handler = file_manager_get_list_handle};
//     httpd_register_uri_handler(server, &file_manager_get);
//     httpd_uri_t file_manager_change = {
//         .uri = "/file_manager/change", // Match all URIs of type /upload/path/to/file
//         .method = HTTP_POST,
//         .user_ctx = base_path,
//         .handler = file_manager_change_handle};
//     httpd_register_uri_handler(server, &file_manager_change);
//     httpd_uri_t file_stream = {
//         .uri = "/file_stream/*", // Match all URIs of type /upload/path/to/file
//         .method = HTTP_POST,
//         .user_ctx = base_path,
//         .handler = file_manager_binary_update_handle};
//     httpd_register_uri_handler(server, &file_stream);
//     httpd_uri_t file_managers = {
//         .uri = "/file_manager/*", // Match all URIs of type /upload/path/to/file
//         .method = HTTP_GET,
//         .user_ctx = base_path,
//         .handler = file_manager_handle};
//     httpd_register_uri_handler(server, &file_managers);
//     httpd_uri_t file_managers_root = {
//         .uri = "/file_manager", // Match all URIs of type /upload/path/to/file
//         .method = HTTP_GET,
//         .user_ctx = base_path,
//         .handler = file_manager_handle};
//     httpd_register_uri_handler(server, &file_managers_root);
//     return;
// }